unit uPropriedade;

interface

uses
  SysUtils,
  Classes,
  TypInfo,

  uConversaoDados,
  uEnumerandos;

type
  TListaProp=class
  private
    FObjeto:TObject;
    FQuantidade:integer;
    FListaProp:PPropList;
    function Get(Indice: integer):PPropInfo;
  public
    function  GetQuantidade:integer;
    function  GetTTipoDado(Indice:integer):                            TTipoDado;
    function  GetNome(Indice:integer):                                 string;
    function  GetNomeTipo(Indice:integer):                             ShortString;
    function  GetValue(Indice:integer):                                Variant;
    function  GetAttributeByName(p_Name:string;p_Atipo:TAttributeType):Variant;

    procedure SetValue(Indice:integer;p_Value:Variant);
    constructor Create(p_Objeto:TObject);overload;
    destructor Free;
  end;

implementation

uses

  Variants;

constructor TListaProp.Create(p_Objeto: TObject);
begin
  FObjeto     := p_Objeto; {Usado para referenciar o objeto nos metodos dessa classe}
  FQuantidade := GetPropList(FObjeto,FListaProp);
end;

destructor TListaProp.Free;
begin
  if Assigned(FListaProp) and (FListaProp <> Nil) then
    FreeMem(FListaProp);
end;

{Resulta o ponteiro da property atraves do indice}
function TListaProp.Get(Indice: integer): PPropInfo;
begin
  result := PPropInfo(FListaProp[Indice]);
end;

function TListaProp.GetNome(Indice:integer): string;
begin
  result := AnsiLowerCase(UTF8ToAnsi(Get(Indice)^.Name));
end;

{Resulta a quantidade de propriedades registradas na classe}
function TListaProp.GetQuantidade: integer;
begin
  result := FQuantidade;
end;

{Resulta o nome do tipo ex: string, integer...}
function TListaProp.GetNomeTipo(Indice: integer):ShortString;
begin
  result := Get(Indice)^.PropType^.Name;
end;

{Resulta o tipo TTipoDado pelo nome do tipo e pelo indice da property}
function TListaProp.GetTTipoDado(Indice: integer): TTipoDado;
begin
  result := TDBaseValue.GetTipoDado(GetNomeTipo(Indice));
end;

{Seta o valor da propriedade de acordo com o parametro p_Value}
procedure TListaProp.SetValue(Indice:integer;p_Value:Variant);
begin
  SetPropValue(FObjeto,GetNome(Indice),p_Value);
end;

{Resulta o valor da property atraves do indice}
function TListaProp.GetValue(Indice: integer): Variant;
begin
  result := GetPropValue(FObjeto,Get(Indice));
end;

{Obtem, atraves do nome da property, o seu valor, o nome do tipo ou o tipo enumerando TAttributeType}
function TListaProp.GetAttributeByName(p_Name:string;p_Atipo:TAttributeType):Variant;
var
  i:integer;
begin
  result := 0;
  for i:=0 to GetQuantidade -1 do
    if GetNome(i) = AnsiLowerCase(p_Name) then
    begin
      case p_Atipo of
        atValue:    result := GetValue(i);
        atTTipoDado:result := TDBaseValue.GetTipoDado(GetNomeTipo(i));
      end;
      Break;
    end;
end;

end.

